package com.link2room.rodimus.service.impl;

import com.link2room.common.enums.BaseSysExceptionEnum;
import com.link2room.common.exception.SysException;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.ExceptionUtil;
import com.link2room.common.util.L2RAssert;
import com.link2room.common.util.StringUtil;
import com.link2room.rodimus.constant.DrawConstant;
import com.link2room.rodimus.dto.result.base.DrawPrizeBaseDto;
import com.link2room.rodimus.entity.DrawAfterDoLogEntity;
import com.link2room.rodimus.entity.DrawLogEntity;
import com.link2room.rodimus.entity.DrawPrizeBaseEntity;
import com.link2room.rodimus.entity.MemberBase;
import com.link2room.rodimus.service.IAfterDrawHandleService;
import com.link2room.rodimus.service.IMemberService;


import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.link2room.enums.exception.RodimusSysExceptionEnum.REDO_DRAW_AFTER_DO_ERROR;

/**
 * Created by LN on 2017/11/7
 */
public abstract class AbstractArfterDrawHandlerServiceImpl implements IAfterDrawHandleService {
    private ExecutorService drawLogExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    @Resource
    private ICommonService commonService;
    @Resource
    private IMemberService memberService;

    @Override
    public void afterDraw(DrawPrizeBaseDto drawPrizeBaseDto) throws Exception {
        String errorMsg = null;
        String resultCode = DrawConstant.DrawAfterDo.RESULT_CODE.SUCCESS;
        try {
            doAfterDraw(drawPrizeBaseDto);
        } catch (Exception e) {
            errorMsg = ExceptionUtil.getExceptionDetail(e);
            resultCode = DrawConstant.DrawAfterDo.RESULT_CODE.FAILED;
            throw e;
        } finally {
            String finalErrorMsg = errorMsg;
            String finalResultCode = resultCode;
            drawLogExecutorService.submit(() -> {
                DrawAfterDoLogEntity log = new DrawAfterDoLogEntity();
                log.setActivityCode(drawPrizeBaseDto.getActivityCode());
                log.setDrawNo(drawPrizeBaseDto.getDrawNo());
                log.setPrizeCode(drawPrizeBaseDto.getCode());
                log.setResultCode(finalResultCode);
                log.setErrorMsg(finalErrorMsg);
                try {
                    commonService.save(log);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }

    @Override
    public void redoAfterDraw(String drawNo, DrawPrizeBaseEntity prizeBase) {
        L2RAssert.stringBlank(drawNo, "[drawNo] is required.");
        DrawAfterDoLogEntity find = new DrawAfterDoLogEntity();
        find.setDrawNo(drawNo);
        DrawAfterDoLogEntity afterDoLog = null;
        String errorMsg = null;
        String resultCode = DrawConstant.DrawAfterDo.RESULT_CODE.SUCCESS;
        try {
            afterDoLog = commonService.findOneEQ(DrawAfterDoLogEntity.class, find);
        } catch (Exception e) {
            throw new SysException(BaseSysExceptionEnum.BASE_FUCATION_OPTION, e);
        }
        L2RAssert.isTrue(null == afterDoLog, new SysException(REDO_DRAW_AFTER_DO_ERROR, "DrawAfterDoLogEntity[drawNo] " + drawNo + "没有记录."));
        L2RAssert.isTrue(!DrawConstant.DrawAfterDo.RESULT_CODE.FAILED.equals(afterDoLog.getResultCode()), new SysException(REDO_DRAW_AFTER_DO_ERROR, "[drawNo] " + drawNo + "状态为" + afterDoLog.getResultCode()));
        DrawLogEntity findDrawLog = new DrawLogEntity();
        findDrawLog.setDrawNo(drawNo);
        DrawLogEntity log = null;
        try {
            log = commonService.findOneEQ(DrawLogEntity.class, findDrawLog);
        } catch (Exception e) {
            throw new SysException(BaseSysExceptionEnum.BASE_FUCATION_OPTION, e);
        }
        L2RAssert.isTrue(null == log, new SysException(REDO_DRAW_AFTER_DO_ERROR, "DrawLogEntity[drawNo] " + drawNo + "没有记录."));
        String openid = log.getOpenid();
        MemberBase memberBase = null;
        try {
            memberBase = memberService.selectMemberByOpenid(null,openid);
        } catch (Exception e) {
            throw new SysException(BaseSysExceptionEnum.BASE_FUCATION_OPTION, e);
        }
        try {
            redoAfterDraw(memberBase,openid,prizeBase);
        } catch (Exception e) {
            errorMsg = ExceptionUtil.getExceptionDetail(e);
            resultCode = DrawConstant.DrawAfterDo.RESULT_CODE.FAILED;
        }finally {
            String finalErrorMsg = errorMsg;
            String finalResultCode = resultCode;
            DrawAfterDoLogEntity finalAfterDoLog = afterDoLog;
            drawLogExecutorService.submit(() -> {
                finalAfterDoLog.setResultCode(finalResultCode);
                if(StringUtil.isNotBlank(finalErrorMsg)){
                    finalAfterDoLog.setErrorMsg(finalAfterDoLog.getErrorMsg()+"\r\n"+finalErrorMsg);
                }
                try {
                    commonService.merge(finalAfterDoLog);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

    }

    abstract void doAfterDraw(DrawPrizeBaseDto drawPrizeBaseDto) throws Exception;

    abstract void redoAfterDraw(MemberBase memberBase,String openid,DrawPrizeBaseEntity prizeBase) throws Exception;
}
